package com.shell.customer.graph.service.impl;

import com.shell.bee.base.utils.StringUtil;
import com.shell.customer.base.dao.CustomerDao;
import com.shell.customer.base.service.CustomerService;
import com.shell.customer.base.vo.CusRecVo;
import com.shell.customer.graph.service.GraphService;
import com.shell.customer.graph.vo.Category;
import com.shell.customer.graph.vo.Graph;
import com.shell.customer.graph.vo.GraphLink;
import com.shell.customer.graph.vo.GraphNode;
import com.shell.customer.po.CusRec;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("graphService")
public class GraphServiceImpl implements GraphService {
	@Autowired
	CustomerDao customerDao;
	@Autowired
	private CustomerService customerService;
	static String[] categoryArr = { "��������", "��������", "������" };

	public Graph findGraph(String grpId, String cusId) {
		if (StringUtil.emptyAndNull(cusId)) {
			return findAllNode(grpId);
		}
		return findCusNode(grpId, cusId);
	}

	private Graph findCusNode(String grpId, String cusId) {
		String[] tagCodes = { "FOCAL_CO", "MEMBER", "SUPPLIER" };
		String[] cusStates = { "E" };
		List<CusRecVo> cusRecs = this.customerDao.findCusForGrp(grpId, null, cusStates, tagCodes, null, null);
		Map<String, CusRecVo> cusMap = new HashMap();
		String rootName = null;
		for (CusRecVo cus : cusRecs) {
			cusMap.put(cus.getCusName(), cus);
			if (cus.getTagCodes().indexOf("FOCAL_CO") != -1) {
				rootName = cus.getCusName();
			}
		}
		if (StringUtil.emptyAndNull(rootName)) {
			CusRecVo root = findRootNode(grpId);
			rootName = root.getCusName();
			cusMap.put(root.getCusName(), root);
		}
		CusRec cus = (CusRec) this.customerService.selectByKey(cusId);

		CusRecVo cusVo = (CusRecVo) cusMap.get(cus.getCusName());
		if (cusVo.getTagCodes().indexOf("FOCAL_CO") != -1) {
			return findAllNode(grpId);
		}
		Graph graph = new Graph();
		graph.setNodes(new HashSet());
		graph.setLinks(new HashSet());

		Set<Category> categories = new HashSet();
		for (String cy : categoryArr) {
			Category category = new Category();
			category.setName(cy);
			categories.add(category);
		}
		graph.setCategories(categories);

		traverseNode(grpId, cus.getCusName(), "0", graph, cusMap, rootName);

		traverseNode(grpId, cus.getCusName(), "1", graph, cusMap, rootName);

		return graph;
	}

	private void traverseNode(String grpId, String origin, String direction, Graph graph, Map<String, CusRecVo> cusMap,
			String rootName) {
		Set<GraphLink> traverseLinks = new HashSet();
		Set<GraphNode> traverseNodes = new HashSet();
		traverseSubNode(grpId, origin, direction, graph, cusMap, rootName, traverseLinks, traverseNodes);
	}

	private void traverseSubNode(String grpId, String origin, String direction, Graph graph,
			Map<String, CusRecVo> cusMap, String rootName, Set<GraphLink> traverseLinks, Set<GraphNode> traverseNodes) {
		CusRecVo cus = (CusRecVo) cusMap.get(origin);
		GraphNode node = getNode(cus);
		if (traverseNodes.contains(node)) {
			return;
		}
		traverseNodes.add(node);
		if (!graph.getNodes().contains(node)) {
			graph.getNodes().add(node);
		}
		String[] tagCodes = { "FOCAL_CO", "MEMBER", "SUPPLIER" };
		Set<GraphLink> links = null;
		GraphLink rootLink;
		if (direction.equals("0")) {
			links = this.customerDao.findGraphLinks(grpId, tagCodes, cus.getCusId(), null);
			if (cus.getCusName().equals(rootName)) {
				List<CusRec> cusRecs = this.customerService.selectCusByGroupIdAndTagCode(grpId, "MEMBER");
				for (CusRec rec : cusRecs) {
					GraphLink link = new GraphLink();
					link.setSource(rootName);
					link.setTarget(rec.getCusName());
					links.add(link);
				}
			}
		} else {
			links = this.customerDao.findGraphLinks(grpId, tagCodes, null, cus.getCusId());
			if (cus.getTagCodes().indexOf("MEMBER") != -1) {
				rootLink = new GraphLink();
				rootLink.setTarget(cus.getCusName());
				rootLink.setSource(rootName);
				links.add(rootLink);
			}
		}
		for (GraphLink link : links) {
			if (!traverseLinks.contains(link)) {
				traverseLinks.add(link);
				if (!graph.getLinks().contains(link)) {
					graph.getLinks().add(link);
				}
				if (direction.equals("0")) {
					traverseSubNode(grpId, link.getTarget(), direction, graph, cusMap, rootName, traverseLinks,
							traverseNodes);
				} else {
					traverseSubNode(grpId, link.getSource(), direction, graph, cusMap, rootName, traverseLinks,
							traverseNodes);
				}
			}
		}
	}

	private Graph findAllNode(String grpId) {
		String[] tagCodes = { "FOCAL_CO", "MEMBER", "SUPPLIER" };
		String[] cusStates = { "E" };
		List<CusRecVo> cusRecs = this.customerDao.findCusForGrp(grpId, null, cusStates, tagCodes, null, null);

		Set<Category> categories = new HashSet();
		for (String cy : categoryArr) {
			Category category = new Category();
			category.setName(cy);
			categories.add(category);
		}
		Object nodes = new HashSet();
		String rootName = null;
		for (CusRecVo rec : cusRecs) {
			if (rec.getTagCodes().indexOf("FOCAL_CO") != -1) {
				rootName = rec.getCusName();
			}
			GraphNode node = getNode(rec);
			((Set) nodes).add(node);
		}
		if (StringUtil.emptyAndNull(rootName)) {
			CusRecVo rec = findRootNode(grpId);
			rootName = rec.getCusName();
			GraphNode node = getNode(rec);
			((Set) nodes).add(node);
		}
		Object links = this.customerDao.findGraphLinks(grpId, tagCodes, null, null);
		setfisrtLinks(rootName, grpId, (Set) links);

		Graph graph = new Graph();
		graph.setNodes((Set) nodes);
		graph.setLinks((Set) links);
		graph.setCategories(categories);
		return graph;
	}

	private CusRecVo findRootNode(String grpId) {
		List<CusRec> cusRecs = this.customerService.selectCusByGroupIdAndTagCode(grpId, "GROUP_ADMIN");
		if ((cusRecs != null) && (cusRecs.size() > 0)) {
			CusRecVo cusVo = new CusRecVo();
			BeanUtils.copyProperties(cusRecs.get(0), cusVo);
			cusVo.setTagCodes("GROUP_ADMIN");
			return cusVo;
		}
		return null;
	}

	private void setfisrtLinks(String rootName, String grpId, Set<GraphLink> links) {
		List<CusRec> cusRecs = this.customerService.selectCusByGroupIdAndTagCode(grpId, "MEMBER");
		for (CusRec rec : cusRecs) {
			GraphLink link = new GraphLink();
			link.setSource(rootName);
			link.setTarget(rec.getCusName());
			links.add(link);
		}
	}

	private GraphNode getNode(CusRecVo rec) {
		GraphNode node = new GraphNode();
		node.setName(rec.getCusName());
		if (StringUtil.notEmpty(rec.getTagCodes())) {
			if (rec.getTagCodes().indexOf("FOCAL_CO") != -1) {
				node.setCategory(categoryArr[0]);
			} else if (rec.getTagCodes().indexOf("MEMBER") != -1) {
				node.setCategory(categoryArr[1]);
			} else if (rec.getTagCodes().indexOf("SUPPLIER") != -1) {
				node.setCategory(categoryArr[2]);
			}
		}
		if (rec.getCusType().equals("FINNER")) {
			node.setCategory(categoryArr[0]);
			node.setValue("��������");
		} else {
			node.setValue(getValue(rec));
		}
		node.setId(rec.getCusId());
		return node;
	}

	private String getValue(CusRecVo rec)
  {
    if (rec.getCusLvl() == 0) {
      return rec.getTagNames();
    }
    String[] levels = { "��", "��", "��", "��", "��", "��", "��", "��", "��", "��" };
    String[] tagNames = rec.getTagNames().split(",");
    String[] tagCodes = rec.getTagCodes().split(",");
    
    int cusLvl = rec.getCusLvl();
    String level = cusLvl + "";
    if (cusLvl <= levels.length) {
      level = levels[(cusLvl - 1)];
    }
    int i = 0;
    for (String tagCode : tagCodes)
    {
      if (tagCode.equals("SUPPLIER")) {
        tagNames[i] = (level + '级' + tagNames[i]);
      }
      i++;
    }
    return String.join(",", tagNames);
  }
}
